package com.example.contest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.bin.david.form.annotation.SmartColumn;
//import com.bin.david.form.annotation.SmartTable;
import com.bin.david.form.core.SmartTable;
import com.bin.david.form.data.style.FontStyle;
import com.huawei.agconnect.AGCRoutePolicy;
import com.huawei.agconnect.AGConnectInstance;
import com.huawei.agconnect.AGConnectOptionsBuilder;
import com.huawei.agconnect.applinking.AGConnectAppLinking;
import com.huawei.agconnect.applinking.AppLinking;
import com.huawei.agconnect.applinking.ShortAppLinking;
import com.huawei.agconnect.auth.AGConnectAuth;
import com.huawei.agconnect.cloud.database.AGConnectCloudDB;
import com.huawei.agconnect.cloud.database.CloudDBZone;
import com.huawei.agconnect.cloud.database.CloudDBZoneConfig;
import com.huawei.agconnect.cloud.database.CloudDBZoneObjectList;
import com.huawei.agconnect.cloud.database.CloudDBZoneQuery;
import com.huawei.agconnect.cloud.database.CloudDBZoneSnapshot;
import com.huawei.agconnect.cloud.database.exceptions.AGConnectCloudDBException;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hmf.tasks.Task;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import java.util.zip.InflaterOutputStream;

import model.personInfo;
import utils.PersonInfo;

public class DatabaseActivity extends AppCompatActivity {
    AGConnectCloudDB mCloudDB;
    CloudDBZoneConfig mConfig;
    CloudDBZone mCloudDBZone;
    private SmartTable table;
    private static final String TAG = "CloudDBWrapper";
    private UiCallBack mUiCallBack = UiCallBack.DEFAULT;
    private static List<personInfo> personInfoList = new ArrayList<>();

    private String shortText;
    private String longText;

    //Applinking相关
    private static final String DOMAIN_URI_PREFIX = "https://contest2.drcn.agconnect.link";
    private static final String DEEP_LINK = "https://zhuanlan.zhihu.com/p/26998793";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_database);

        AGConnectAppLinking.getInstance();
        AGConnectAppLinking.getInstance()
                .getAppLinking(this)
                .addOnSuccessListener(
                        resolvedLinkData -> {
                            Uri deepLink = null;
                            if (resolvedLinkData != null) {
                                deepLink = resolvedLinkData.getDeepLink();
                            }

                        })
                .addOnFailureListener(
                        e -> {
                            Log.w("MainActivity", "getAppLinking:onFailure", e);
                        });

        CreatApplinking();
        initView();

        findViewById(R.id.login_out).setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                AGConnectAuth.getInstance().signOut();

                Intent intent = new Intent();
                intent.setClass(DatabaseActivity.this, LoginActivity.class);
                startActivity(intent);
                Log.i(TAG, "onClick: log out successfully");
            }
        });
    }

    private void CreatApplinking() {
        AppLinking.Builder builder =
                new AppLinking.Builder()
                        .setUriPrefix(DOMAIN_URI_PREFIX)
                        .setDeepLink(Uri.parse(DEEP_LINK))
                        .setAndroidLinkInfo(new AppLinking.AndroidLinkInfo.Builder().build())
                        .setCampaignInfo(
                                new AppLinking.CampaignInfo.Builder()
                                        .setName("HDC")
                                        .setSource("Huawei")
                                        .setMedium("App")
                                        .build());
        builder.buildShortAppLinking(ShortAppLinking.LENGTH.SHORT)
                .addOnSuccessListener(shortAppLinking -> {
                    shortText = shortAppLinking.getShortUrl().toString();
                    //shortTextView.setText(shortText);
                    Log.i("MainActivity", "createAppLinking of shortText: "+shortText);
                })
                .addOnFailureListener(
                        e -> {
                            showError(e.getMessage());
                        });
        longText = builder.buildAppLinking().getUri().toString();
        //longTextView.setText(longText);
        Log.i("MainActivity", "createAppLinking of shortText: "+shortText);
    }

    private void showError(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    private void initView() {
        //初始化云数据库
        AGConnectCloudDB.initialize(getApplicationContext());
        AGConnectInstance instance = AGConnectInstance.buildInstance(new AGConnectOptionsBuilder().setRoutePolicy(AGCRoutePolicy.CHINA).build(getApplicationContext()));
        mCloudDB = AGConnectCloudDB.getInstance(instance, AGConnectAuth.getInstance(instance));
        Log.i(TAG,"The cloudDB is" + mCloudDB);
        try {
            mCloudDB.createObjectType(model.ObjectTypeInfoHelper.getObjectTypeInfo());
            mConfig = new CloudDBZoneConfig("personInfoZone",
                    CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
                    CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
            mConfig.setPersistenceEnabled(true);
            Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true);
            openDBZoneTask.addOnSuccessListener(new OnSuccessListener<CloudDBZone>() {
                @Override
                public void onSuccess(CloudDBZone cloudDBZone) {
                    Log.i("open clouddbzone", "open cloudDBZone success");
                    mCloudDBZone = cloudDBZone;
                    //开始绑定数据
                    bindData();
                    // Add subscription after opening cloudDBZone success
                    //addSubscription();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    Log.w("open clouddbzone", "open cloudDBZone failed for " + e.getMessage());
                }
            });
        } catch (AGConnectCloudDBException e) {
            Toast.makeText(DatabaseActivity.this, "initialize CloudDB failed" + e, Toast.LENGTH_LONG).show();
        }
    }

    private void bindData() {
        CloudDBZoneQuery<personInfo> query = CloudDBZoneQuery.where(personInfo.class);
        queryPersonInfo(query);
    }


    private List<personInfo> queryPersonInfo(CloudDBZoneQuery<personInfo> query) {
        if (mCloudDBZone == null) {
            Log.w(TAG, "CloudDBZone is null, try re-open it");
            return null;
        }

        Task<CloudDBZoneSnapshot<personInfo>> queryTask = mCloudDBZone.executeQuery(query,
                CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
        //List<personInfo> tmpInfoList = new ArrayList<>();
        queryTask.addOnSuccessListener(new OnSuccessListener<CloudDBZoneSnapshot<personInfo>>() {
            @Override
            public void onSuccess(CloudDBZoneSnapshot<personInfo> snapshot) {
                try {
                    personInfoList = processQueryResult(snapshot);
                } catch (AGConnectCloudDBException e) {
                    Log.e(TAG, "onfailed: "+e.getErrMsg() );
                }
                Log.i(TAG, "onSuccess: query result success");
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                mUiCallBack.updateUiOnError("Query failed");
                Log.i(TAG, "onSuccess: query result failed");
            }
        });
        return personInfoList;
    }

    private List<personInfo> processQueryResult(CloudDBZoneSnapshot<personInfo> snapshot) throws AGConnectCloudDBException {
        CloudDBZoneObjectList<personInfo> bookInfoCursor = snapshot.getSnapshotObjects();
        List<personInfo> bookInfoList = new ArrayList<>();
        List<PersonInfo> list = new ArrayList<>();
        table = findViewById(R.id.table);
        try {
            while (bookInfoCursor.hasNext()) {
                personInfo info = bookInfoCursor.next();
                bookInfoList.add(info);
                list.add(new PersonInfo(info.getId(),info.getName(),info.getAge(),info.getHasInoculate()==true?"是":"否",info.getCardNo()));
//                list.add(new PersonInfo(1,"xuhao",34,true,"12321"));
            }
        } catch (AGConnectCloudDBException e) {
            Log.w(TAG, "processQueryResult: " + e.getMessage());
        } finally {
            snapshot.release();
            mCloudDB.closeCloudDBZone(mCloudDBZone);
        }
        table.setData(list);
        table.getConfig().setContentStyle(new FontStyle(50, Color.BLUE));
        mUiCallBack.onAddOrQuery(bookInfoList);
        return bookInfoList;
    }

    public interface UiCallBack {
        UiCallBack DEFAULT = new UiCallBack() {
            @Override
            public void onAddOrQuery(List<personInfo> bookInfoList) {
                Log.i(TAG, "Using default onAddOrQuery");
            }

            @Override
            public void onSubscribe(List<personInfo> bookInfoList) {
                Log.i(TAG, "Using default onSubscribe");
            }

            @Override
            public void onDelete(List<personInfo> bookInfoList) {
                Log.i(TAG, "Using default onDelete");
            }

            @Override
            public void updateUiOnError(String errorMessage) {
                Log.i(TAG, "Using default updateUiOnError");
            }
        };


        void onAddOrQuery(List<personInfo> bookInfoList);

        void onSubscribe(List<personInfo> bookInfoList);

        void onDelete(List<personInfo> bookInfoList);

        void updateUiOnError(String errorMessage);
    }
}